var P4={
	exec:function(cmd){
		var errFileName=File.getFullTempName();
		var outFileName=File.getFullTempName();
		
		var ret={};
		var fullCmd='cmd /c p4 '+cmd+' 2>'+errFileName+' 1>'+outFileName;
		//alert(fullCmd);
		ret.exitCode=Shell.run(fullCmd);
		//alert(ret.exitCode);
		ret.err=null;
		ret.out=null;

		try{
			ret.out=File.readAll(outFileName);
		}catch(e){}			
		try{
			ret.err=File.readAll(errFileName);
		}catch(e){}
		
		if(ret.exitCode!=0){
			throw this.generateException(ret.err);
		}
		return ret;
	},
	execAsync:function(cmd,callbacker,param){
		AsyncProcessHelper.exec(
			'cmd /c P4 '+cmd,
			callbacker,
			param,
			100
		);
	},
	
	/*
	
	loginInfo:
	{
		server:"tw-p4proxy:1667",
		workspace:"default.al_siao.SMEX-Lead",
		account:"al_siao",
		password:"xxxx"
	}
	
	*/
	login:function(loginInfo,callbacker,param){
		AsyncProcessHelper.exec(
			Environment.getScriptFolderPath()+'\\p4Login.bat "'+
			[
				loginInfo.server,
				loginInfo.workspace,
				loginInfo.account,
				loginInfo.password
			].join('" "')+'"'
			,
			callbacker,
			/*{
				onFinish:function(param){
					if(callbacker)
						callbacker.
					
				},
				param:param
			},*/
			param,
			100
		);
	},
	
	/*
	
	callbacker:{
		onFinish:function(
			{
				isSuccess:bool,
				changeListNumber:string,
				time:Date,
				copyIntoList
				[
					string,ex://SMB/CSM/Int/CSM-5.1-INT/CSM/installshield/ServerSetup/Script Files/SetupDialog.h#5
					...
				],
				exception, //if failed
			}		
		),
	}
	*/
	getFileLogAsync:function(path,callbacker){

		this.execAsync(
			'filelog -t -m 1 "'+path+'"',
			{
				onFinish:function(param)
				{

					var ret={};
					if(param.exitCode){
						//we have some error
						ret.isSuccess=false;
						ret.exception=this.generateException(param.err);
					}
					else
					//success
					{
						ret.isSuccess=true;
						//"... ... copy into "
						var lines=param.out.split('\n');
						var parts = /change (\d+) edit on (\d{4}\/\d{2}\/\d{2} \d{2}:\d{2}:\d{2})/.exec(lines[1]);
						ret.changeListNumber=parts[1];
						ret.time=new Date(parts[2]);
						ret.copyList=[];
						for(var i=2;i<lines.length;++i){
							if(lines[i].length==0)continue;
							ret.copyList.push(
								/copy into (.+)/.exec(lines[i])[1]
							);
						}
					}
					callbacker.onFinish(ret);
				}
			}
		);	
	},
	getFileLog:function(path){
		//alert(path);
		var r=this.exec('filelog -t "'+path+'"');
		var ret={
			isSuccess:false,
			logItems:[]
		};
		if(r.exitCode==1){
			//we have some error
			ret.isSuccess=false;
			ret.exception=this.generateException(r.err);
		}
		else
		//success
		{
			ret.isSuccess=true;
			if(r.out==null){
				ret.isSuccess=false;
				ret.exception=this.generateException(r.err);
			}else{
			
				var lines=r.out.split('\n');

				var activeLogItem=null;
				for(var i=1;i<lines.length;++i){
					//... #15 change
					var parts = /\.{3} #(\d+) change (\d+) (edit|integrate) on (\d{4}\/\d{2}\/\d{2} \d{2}:\d{2}:\d{2})/.exec(lines[i]);
					if(parts!=null)
					{
						activeLogItem={
							revision:parseInt(parts[1]),
							time:new Date(parts[4]),
							copyList:[]
						}
						ret.logItems.push(activeLogItem);
						continue;
					}
					
					var match=/\.{3} \.{3} (copy into|edit into) (.+)/.exec(lines[i]);
					if(match!=null)
					{
						activeLogItem.copyList.push({
							action:match[1],
							path:match[2]
						});
						continue;
					}
				}
			}
		}
		return ret;
	},
	/*
		err:string
		return {
			message:string,
		}
	*/
	generateException:function(errString){
		
		var ret={};
		
		ret.message=errString;
		ret.type='P4';
		return ret;
	}
}

var P4Path={
	create:function(
		segment,		// "SMB"
		projectName,	// "CSM"
		codeLine,		// "Dev"
		version,		// "6.0"
		language,		// null means not L10N version, "en" means l10n/en/
		projectPath,	// path relative to project root, ex "/src/buildAll.sln"
		revision		// null means not reversion
		)
	{
		if(language=="")language=null;
		
		var ret={
			getCodeLine:function(){
				return this.codeLine;
			},
			setCodeLine:function(codeLine){
				this.codeLine=codeLine;
			},
			getVersion:function(){
				return this.version;
			},
			getCodeLinePostfix:function(){
				switch(this.codeLine){
				case 'Dev':
					return '';
				case 'Int':
					return '-INT';
				case 'Rel':
					return '-R';
				}
				alert('getCodeLinePostfix not implemented');
			},
			getFullPathWithoutRevision:function(){
				var ret= "//"+
				[
					this.segment,
					this.projectName,
					this.codeLine,
					this.projectName+'-'+this.version+this.getCodeLinePostfix(),
					this.projectName
				].join('/');
				
				if(this.language!=null)
				{
					
					ret+='/L10N/'+this.language;
				}
				
				ret+=this.projectPath;

				return ret;
			},
			getFullPath:function(){
				var ret=this.getFullPathWithoutRevision();
				if(this.revision!=null)
					ret+="#"+this.revision;
				return ret;
			},
			segment:segment,
			projectName:projectName,
			codeLine:codeLine,
			version:version,
			language:language,
			projectPath:projectPath,
			revision:parseInt(revision)
		};
		return ret;
	},
	fromString:function(path){
		// //(\w+)/(\w+)/([^/]+)/[^-/]+-([0-9.]+)(-\w+)?/\w+(/L10N/([a-zA-Z_]+))?([^#]*)(#(\d+))?
		var pattern=/\/\/(\w+)\/(\w+)\/([^\/]+)\/[^-\/]+-([0-9.]+)(-\w+)?\/\w+(\/L10N\/([a-zA-Z_]+))?([^#]*)(#(\d+))?/;
		var parts = pattern.exec(path); 
		if(parts==null)return null;
		//alert(parts);
		return this.create(
			parts[1],
			parts[2],
			parts[3],
			parts[4],
			parts[7],
			parts[8],
			parts[10]
			);
			
	}
}